package com.guofs.project.common.utils.tree.base;

import com.google.common.base.Predicate;
import com.guofs.project.common.utils.function.BiFunction;
import com.guofs.project.common.utils.function.BinaryOperator;

import java.io.Serializable;
import java.util.List;

/**
 * 树类型对象基本需要实现的方法
 * <T>
 * @author 郭芳诗
 * @date 2019/1/18 14:40
 */
public interface TreeBase<N, K> extends Serializable {

    /**
     * 获取当前节点的唯一标识
     *
     * @param node 当前节点
     * @return 当前节点的唯一标识
     */
    K getKey(N node);

    /**
     * 获取当前节点的父节点的唯一标识
     *
     * @param node 当前节点
     * @return 父节点的唯一标识
     */
    K getParentKey(N node);

    /**
     * 节点放置
     * @param node 节点
     */
    void putNode(N node);

    /**
     * 遍历循环节点<br/>
     * <h2>函数内部</h2>  <br/>
     * true --> 继续循环 直至最终节点 ;<br/>
     * false --> 跳出循环
     * @param predicate 操作节点对象函数
     */
    void forEach(Predicate<N> predicate);

    /**
     * 依据唯一标识查找节点
     * @param key 唯一标识
     * @return 该标识的节点
     */
    N getNodeByKey(K key);

    /**
     * 获取父节点信息
     * @param key 被获取父节点的子节点唯一标识
     * @return 父节点信息
     */
    N getParent(K key);

    /**
     * 获取树根
     * @return 树根节点数据
     */
    List<N> getRoot();

    /**
     * 获取子节点列表
     * @param key 被获取子节点的节点唯一标识
     * @return 子节点列表
     */
    List<N> getChildren(K key);

    /**
     * 获取所有节点<h3>无序</h3>
     * @return 所有节点信息
     */
    List<N> findAll();

    /**
     * 查找上一级的树(从树根向下传参)
     * @param start 起始值
     * @param node 查找的节点
     * @param accumulator 转换函数
     * @param <P> 转换的值的类型
     * @return 转换的值
     */
    <P> P findParents(P start, N node, BiFunction<P, ? super N, P> accumulator);

    /**
     * 查找上一级的树(从当前节点向树根传参)
     * @param start 起始值
     * @param node 查找的节点
     * @param accumulator 转换函数
     * @param <P> 转换的值的类型
     * @return 转换的值
     */
    <P> P findParentsReversal(P start, N node, BiFunction<P, ? super N, P> accumulator);
}
